﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ITAP.ShprossesBuilder.Modelling;
using ITAP.ShprossesBuilder.Editor;
using ITAP.ShprossesBuilder.Modelling.Components;
using ITAP.ShprossesBuilder.Calculations;
using ITAP.ShprossesBuilder.Properties;
using ITAP.Core.Modelling;
using ITAP.Core.Calculations;

namespace ITAP.ShprossesBuilder.Operations
{
    enum DiagonalOffsetTo
    {
        UpRight, 
        UpLeft, 
        DownLeft, 
        DownRight
    }
    public class CommandMoveComponentsWithOffsetDiagonal : IOperation
    {
        private ModelControl modelControl;
        #region IOperation Members

        public string Name
        {
            get { return "Смещение компонентов по диагонали"; }
        }

        public OperationGroup OperationGroup
        {
            get { return OperationGroup.Other; }
        }

        public System.Drawing.Image Thumbnail
        {
            get { return Resources.MoveWithOffsetDiagonal.ToBitmap(); }
        }

        public void Execute(ModelControl modelControl)
        {
            this.modelControl = modelControl;
            ContextMenuStrip menuStrip = new ContextMenuStrip();

            EventHandler handler = new EventHandler(OnItemClick);
            ToolStripItem rightUp = new ToolStripMenuItem("Вправо вверх", null, handler);
            rightUp.Tag = DiagonalOffsetTo.UpRight;
            menuStrip.Items.Add(rightUp);
            ToolStripItem upLeft = new ToolStripMenuItem("Влево вверх", null, handler);
            upLeft.Tag = DiagonalOffsetTo.UpLeft;
            menuStrip.Items.Add(upLeft);
            ToolStripItem leftDown = new ToolStripMenuItem("Влево вниз", null, handler);
            leftDown.Tag = DiagonalOffsetTo.DownLeft;
            menuStrip.Items.Add(leftDown);
            ToolStripItem downRight = new ToolStripMenuItem("Вправо вниз", null, handler);
            downRight.Tag = DiagonalOffsetTo.DownRight;
            menuStrip.Items.Add(downRight);

            menuStrip.Show(Cursor.Position);

        }

        public bool CanUndo
        {
            get { return true; }
        }

        #endregion

        private void OnItemClick(object sender, EventArgs e)
        {
            ToolStripMenuItem item = sender as ToolStripMenuItem;
            DiagonalOffsetTo offset = (DiagonalOffsetTo)item.Tag;

            MoveWithOffsetFormDiagonal moveForm = new MoveWithOffsetFormDiagonal();
            if (moveForm.ShowDialog() != DialogResult.OK)
                return;

            IComponent component = null;
            foreach (IComponent selectedComponent in this.modelControl.ModelContainer.SelectedComponentsStack)
            {
                if (selectedComponent.Parent == null)
                    continue;

                if (selectedComponent is Shpross || selectedComponent is ShprossConnector)
                {
                    if (moveForm.OffsetWithCopy)
                    {
                        component = selectedComponent.Copy();
                        component.SerialNumber = 0;
                    }
                    else
                        component = selectedComponent;

                    if (component is Shpross)
                    {
                        Shpross shpross = component as Shpross;
                        if (shpross.SelectedPoint != ShprossPoints.Start && shpross.SelectedPoint != ShprossPoints.End && shpross.SelectedPoint != ShprossPoints.Center)
                            continue;
                        ModelPoint moveTo = this.GetMoveToPoint(shpross.SelectedPointPosition, offset, moveForm.OffsetRelative, moveForm.Offset);
                        if (shpross.SelectedPoint == ShprossPoints.Start)
                            shpross.MoveStartPointTo(moveTo, shpross.Parent.BoundingBox, false);
                        else if (shpross.SelectedPoint == ShprossPoints.End)
                            shpross.MoveEndPointTo(moveTo, shpross.Parent.BoundingBox, false);
                        else if (shpross.SelectedPoint == ShprossPoints.Center)
                            shpross.MoveTo(moveTo, shpross.Parent.BoundingBox);
                    }
                    if (component is ShprossConnector)
                    {
                        ShprossConnector connector = component as ShprossConnector;
                        ModelPoint moveTo = this.GetMoveToPoint(connector.Position, offset, moveForm.OffsetRelative, moveForm.Offset);
                        connector.MoveTo(moveTo, selectedComponent.Parent.BoundingBox);
                    }
                    selectedComponent.Parent.AddInnerComponent(component);
                    component.Update();
                }
            }
            this.modelControl.UpdateModel();
        }

        private ModelPoint GetMoveToPoint(ModelPoint source, DiagonalOffsetTo offset, DiagonalOffsetRelative offsetRelative, int offsetValue)
        {
            ModelVector vector = null;
            switch (offset)
            {
                case DiagonalOffsetTo.UpRight:
                    vector = new ModelVector(offsetValue, 0);
                    break;
                case DiagonalOffsetTo.UpLeft:
                    vector = new ModelVector(0, offsetValue);
                    break;
                case DiagonalOffsetTo.DownLeft:
                    vector = new ModelVector(-offsetValue, 0);
                    break;
                case DiagonalOffsetTo.DownRight:
                    vector = new ModelVector(0, -offsetValue);
                    break;
            }
            vector = vector.Rotate(new Angle(Math.PI / 4));
            if (offsetRelative == DiagonalOffsetRelative.ToDiagonal)
                vector.Length = offsetValue;
            else
            {
                double hypotenuse = offsetValue / Math.Cos(Math.PI / 4);
                vector.Length = hypotenuse;
            }
            
            ModelPoint result = ModelCalculations.GetOffsetPoint(source, vector);
            return result;
        }
    }
}
